﻿using System;
using System.Configuration;
using System.Globalization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace Soul.Common.WCFExtensions
{
    class UnityInstanceProvider : IInstanceProvider
    {
        private Type _contractType;
        private string _containerName;

        public UnityInstanceProvider(Type contractType, string containerName)
        {
            if (contractType == null)
            {
                throw new ArgumentNullException("contractType");
            }

            this._containerName = containerName;
            this._contractType = contractType;
        }

        #region IInstanceProvider Members

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            UnityConfigurationSection unitySection = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
            if (unitySection == null)
            {
                throw new ConfigurationErrorsException(string.Format(CultureInfo.CurrentCulture, "asdf"));
            }

            IUnityContainer container = new UnityContainer();

            unitySection.Configure(container, string.IsNullOrEmpty(this._containerName) ? unitySection.Containers.Default.Name : this._containerName);

            if (!container.IsRegistered(typeof(IUnityContainer)))
            {
                container.RegisterInstance<IUnityContainer>(container);
            }

            if (!container.IsRegistered(this._contractType))
            {
                container.RegisterType(this._contractType, instanceContext.Host.Description.ServiceType);
            }

            return container.Resolve(this._contractType);
        }

        public object GetInstance(InstanceContext instanceContext)
        {
            return this.GetInstance(instanceContext, null);
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            IDisposable disposable = instance as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        }

        #endregion
    }

}
